package me.hetong.caigou.ui.chessboard;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import cn.hutool.log.StaticLog;
import javafx.animation.KeyFrame;
import javafx.animation.KeyValue;
import javafx.animation.Timeline;
import javafx.application.Platform;
import javafx.scene.image.ImageView;
import javafx.scene.input.MouseButton;
import javafx.scene.layout.AnchorPane;
import javafx.scene.paint.Paint;
import javafx.scene.shape.Rectangle;
import javafx.util.Duration;
import me.hetong.caigou.Global;
import me.hetong.caigou.entity.Chess;
import me.hetong.caigou.entity.Zhao;
import me.hetong.caigou.ui.stage.IndexStage;
import me.hetong.caigou.ui.view.LineChartWebView;
import me.hetong.caigou.util.ChessUtils;
import me.hetong.caigou.util.FenUtils;
import me.hetong.caigou.util.ZhaoFaUtils;

import java.util.ArrayList;
import java.util.List;

import static me.hetong.caigou.Global.*;

/**
 * 实战对局，保存的页面
 *
 * @author hetong
 */
public class ChessBoardWar {
    public static final AnchorPane ROOT = new AnchorPane();
    public static Chess click1;
    public static int index = -1;
    public static ImageView toImageView = null;
    public static boolean isInfering = false;// 是否在推演模式
    private static final Rectangle inferRectangle = new Rectangle();// 推演模式的遮罩
    private static int inferIndex = -1;// 演示模式下着法下标
    public static List<Zhao> inferList = new ArrayList<>();// 此次演示着法列表

    static {

        {
            /*
            初始化推演模式
             */
            inferRectangle.setWidth(ChessboardWarOnlyBoard.CANVAS.getWidth());
            inferRectangle.setHeight(ChessboardWarOnlyBoard.CANVAS.getHeight());
            inferRectangle.setFill(Paint.valueOf("#000"));
            inferRectangle.setOpacity(0.2);
        }

        ROOT.getChildren().add(ChessboardWarOnlyBoard.CANVAS);
        ChessboardWarImage.initChessList(null);
        ROOT.setOnMouseClicked(mouseEvent -> {
            if (mouseEvent.getButton().equals(MouseButton.PRIMARY)) {

                if (!isInfering) {
                    inferModel();
                }
                int x = (int) (mouseEvent.getX() - ChessboardWarOnlyBoard.GRID_SIZE / 2) / ChessboardWarOnlyBoard.GRID_SIZE;
                int y = (int) (mouseEvent.getY() - ChessboardWarOnlyBoard.GRID_SIZE / 2) / ChessboardWarOnlyBoard.GRID_SIZE;

                Chess chess = ChessboardWarImage.getChess(x, y);

                if (click1 == null) {
                    if (chess != null) {

                        Zhao zhao = Global.engine.getZhao();
                        if (zhao != null) {
                            Chess chess1 = ChessboardWarImage.getChess(zhao.getX2(), zhao.getY2());
                            if (chess1 != null) {
                                if (chess.getType().equals(chess1.getType())) {
                                    IndexStage.VIEW.getMessageBean().info("现在轮到对方走棋");
                                    Global.playSound(Global.ERROR_AUDIO);
                                    return;
                                }
                            }
                        } else {
                            if (!chess.getType().equals("w")) {
                                IndexStage.VIEW.getMessageBean().info("红方先走");
                                Global.playSound(Global.ERROR_AUDIO);
                                return;
                            }
                        }
                        click1 = chess;
                        ChessboardWarImage.setToImageViewLocation(x, y);
                        ChessboardWarImage.clearFromLocation();
                        StaticLog.info("选择棋子,{},{},{}", chess.getName(), chess.getX(), chess.getY());
                        ChessUtils.canMove(chess);
                    }
                } else {
                    if (chess == null) {
                        // 走子
                        inferIndex++;
                        Zhao zhao = new Zhao(click1.getX(), click1.getY(), x, y);
                        zhao.setRed(click1.getType().equals("w"));
                        zhao.setIdx(inferIndex);
                        inferList.add(zhao);
                        StaticLog.info("走子,{},{}", click1.getName(), JSONUtil.toJsonStr(zhao));

                        if (!ChessUtils.moveValidate(click1, zhao)) {
                            Global.playSound(Global.ERROR_AUDIO);
                            return;
                        }

                        step(zhao);
                    } else {
                        // 点击的是同一个棋子则取消选择
                        if (click1 == chess) {
                            click1 = null;
                            ROOT.getChildren().remove(toImageView);
                            ChessboardWarImage.clearImageViewLocation();
                            StaticLog.info("取消棋子,{}", chess.getName());
                        } else {
                            // 点击的是自己方的棋子则重新选择
                            if (click1.getType().equals(chess.getType())) {
                                click1 = chess;
                                ChessboardWarImage.setToImageViewLocation(x, y);
                                StaticLog.info("切换棋子,{},{},{}", chess.getName(), chess.getX(), chess.getY());
                                ChessUtils.canMove(chess);
                            } else {
                                //  吃子
                                inferIndex++;
                                Zhao zhao = new Zhao(click1.getX(), click1.getY(), chess.getX(), chess.getY());
                                zhao.setRed(click1.getType().equals("w"));
                                zhao.setIdx(inferIndex);
                                inferList.add(zhao);
                                StaticLog.info("吃子,{},{}", click1.getName(), JSONUtil.toJsonStr(zhao));

                                if (!ChessUtils.moveValidate(click1, zhao)) {
                                    Global.playSound(Global.ERROR_AUDIO);
                                    return;
                                }

                                step(zhao);
                            }
                        }
                    }
                }
            }
        });
    }

    /**
     * 吃子或者走子
     *
     * @param zhao
     */
    public static void step(Zhao zhao) {
        try {
            click1 = null;

            Global.playSound(Global.MOVE_AUDIO);

            createTimeline(zhao);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 创建棋子动画
     *
     * @param zhao
     * @return
     */
    private static Timeline createTimeline(Zhao zhao) {

        ChessboardWarImage.setFromImageViewLocation(zhao.getX1(), zhao.getY1());
        ChessboardWarImage.clearToLocation();

        Chess chess1 = ChessboardWarImage.getChess(zhao.getX1(), zhao.getY1());
        if (chess1 == null) {
            return null;
        }

        // 把当前棋子置顶层
        chess1.getImageView().toFront();

        if (isInfering) {
            ROOT.getChildren().remove(inferRectangle);
            ROOT.getChildren().add(inferRectangle);
        }

        KeyValue kv1x = new KeyValue(chess1.getImageView().xProperty(), zhao.getX1() * ChessboardWarOnlyBoard.GRID_SIZE + ChessboardWarImage.PY);
        KeyValue kv1y = new KeyValue(chess1.getImageView().yProperty(), zhao.getY1() * ChessboardWarOnlyBoard.GRID_SIZE + ChessboardWarImage.PY);
        KeyFrame kf1 = new KeyFrame(Duration.millis(0), "kf1", event -> {
        }, kv1x, kv1y);

        KeyValue kv2x = new KeyValue(chess1.getImageView().xProperty(), zhao.getX2() * ChessboardWarOnlyBoard.GRID_SIZE + ChessboardWarImage.PY);
        KeyValue kv2y = new KeyValue(chess1.getImageView().yProperty(), zhao.getY2() * ChessboardWarOnlyBoard.GRID_SIZE + ChessboardWarImage.PY);
        KeyFrame kf2 = new KeyFrame(Duration.millis(config.getMoveAnimateTime()), "kf2", event -> {
        }, kv2x, kv2y);

        Timeline timeline = new Timeline();
        timeline.getKeyFrames().addAll(kf1, kf2);
        timeline.setOnFinished(event -> {

            if (StrUtil.isBlank(zhao.getFen1())) {
                zhao.setFen1(FenUtils.chessListToFen(ChessboardWarImage.chessList));
                ZhaoFaUtils.getZhaoFaName(ChessboardWarImage.chessList, zhao);
            }

            removeTargetChess(zhao.getX2(), zhao.getY2());
            // 更新棋子坐标
            chess1.setX(zhao.getX2());
            chess1.setY(zhao.getY2());

            ChessboardWarImage.setToImageViewLocation(zhao.getX2(), zhao.getY2());

            if (StrUtil.isBlank(zhao.getFen2())) {
                zhao.setFen2(FenUtils.chessListToFen(ChessboardWarImage.chessList));
            }

            LineChartWebView.transFromMatchData();
            LineChartWebView.setHighLight(zhao.getIdx());
            Global.engine.search(zhao);
        });

        timeline.play();

        return timeline;
    }

    /**
     * 删除目标位置棋子
     *
     * @param x
     * @param y
     */
    public static void removeTargetChess(int x, int y) {
        for (Chess li : ChessboardWarImage.chessList) {
            if (li.getX() == x && li.getY() == y) {
                ChessboardWarImage.chessList.remove(li);
                ROOT.getChildren().remove(li.getImageView());
                return;
            }
        }
    }

    public static void begin() {
        Platform.runLater(() -> {
            if (qipu != null && CollectionUtil.isNotEmpty(qipu.getZhaoList())) {
                if (!isInfering) {
                    ChessboardWarImage.initChessList(qipu.getZhaoList().get(0).getFen1());
                    index = -1;
                    inferIndex = -1;
                    ChessboardWarImage.clearImageViewLocation();
                    LineChartWebView.setHighLight(-1);
                    Global.playSound(MOVE_AUDIO);
                }
            }
        });
    }

    public static void end() {
        if (!isInfering) {
            if (qipu != null && CollUtil.isNotEmpty(qipu.getZhaoList())) {
                index = qipu.getZhaoList().size() - 1;
                Zhao zhao = qipu.getZhaoList().get(index);
                ChessboardWarImage.initChessList(zhao.getFen2());
                ChessboardWarImage.setFromImageViewLocation(zhao.getX1(), zhao.getY1());
                ChessboardWarImage.setToImageViewLocation(zhao.getX2(), zhao.getY2());
                LineChartWebView.setHighLight(index);
                engine.search(zhao);
                Global.playSound(MOVE_AUDIO);
            }
        }
    }

    public static void prev() {
        try {
            click1 = null;
            if (isInfering) {
                // 推演模式
                Zhao zhao = listPro(inferList, inferIndex - 1);
                if (zhao != null) {
                    inferIndex--;
                    ChessboardWarImage.initChessList(zhao.getFen2());
                    ROOT.getChildren().remove(inferRectangle);
                    ROOT.getChildren().add(inferRectangle);
                    ChessboardWarImage.setFromImageViewLocation(zhao.getX1(), zhao.getY1());
                    ChessboardWarImage.setToImageViewLocation(zhao.getX2(), zhao.getY2());
                    inferList.remove(inferIndex + 1);
                    Global.engine.search(zhao);
                    Global.playSound(Global.BACK_AUDIO);
                } else {
                    // 说明推演模式下已经没有上一着了，则自动返回正常模式
                    IndexStage.VIEW.getMessageBean().info("正常模式");
                    inferModel();
                }
            } else {
                // 正常模式
                if (qipu != null && CollUtil.isNotEmpty(qipu.getZhaoList())) {
                    Zhao zhao = listPro(qipu.getZhaoList(), index - 1);
                    if (zhao != null) {
                        index--;
                        ChessboardWarImage.initChessList(zhao.getFen2());
                        ChessboardWarImage.setFromImageViewLocation(zhao.getX1(), zhao.getY1());
                        ChessboardWarImage.setToImageViewLocation(zhao.getX2(), zhao.getY2());
                        Global.engine.search(zhao);
                        Global.playSound(Global.BACK_AUDIO);
                        LineChartWebView.setHighLight(index);
                    } else {
                    }
                } else {
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static void next() {
        Platform.runLater(() -> {
            try {
                if (qipu != null && CollUtil.isNotEmpty(qipu.getZhaoList())) {
                    Zhao zhao = listPro(qipu.getZhaoList(), index + 1);
                    if (zhao != null) {
                        index++;
                        ChessboardWarImage.initChessList(zhao.getFen1());
                        step(zhao);
                    } else {
                    }
                } else {
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        });
    }

    /**
     * 推荐模式切换
     * 在进入推演模式前需要记住当前局面，退出推演模式后恢复局面
     */
    public static void inferModel() {
        isInfering = !isInfering;
        if (isInfering) {

            inferIndex = -1;
            inferList = new ArrayList<>();

            ROOT.getChildren().add(inferRectangle);
            IndexStage.VIEW.getMessageBean().info("进入推演模式");
        } else {
            // 退出推演模式
            if (index >= 0 && qipu != null && CollUtil.isNotEmpty(qipu.getZhaoList())) {
                Zhao zhao = qipu.getZhaoList().get(index);
                if (zhao != null) {
                    Global.engine.search(zhao);
                    ChessboardWarImage.initChessList(zhao.getFen2());
                    LineChartWebView.setHighLight(index);
                    ChessboardWarImage.setFromImageViewLocation(zhao.getX1(), zhao.getY1());
                    ChessboardWarImage.setToImageViewLocation(zhao.getX2(), zhao.getY2());
                }
            } else {
                ChessboardWarImage.initChessList(null);
            }

            ROOT.getChildren().remove(inferRectangle);
            IndexStage.VIEW.getMessageBean().info("退出推演模式");
        }
    }

    /**
     * 从列表中获取对象，如果为越界直接返回空
     *
     * @param list
     * @param index
     * @param <T>
     * @return
     */
    public static <T> T listPro(List<T> list, int index) {
        if (null == list) {
            return null;
        }

        final int size = list.size();
        if (0 == size) {
            return null;
        }

        if (index > size - 1 || index < 0) {
            return null;
        }

        return list.get(index);
    }
}